#! /bin/sh /usr/share/dpatch/dpatch-run
## 22_CVE-2008-5824.dpatch by Stefan Fritsch <sf@debian.org>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: Remove confusion between samples per block and frames perl block, to
## DP: avoid buffer overflow (probably samplesPerBlock should be renamed to
## DP: FramesPerBlock). Add sanity checks inspired by sox source code.

@DPATCH@
diff -urNad audiofile-0.2.6~/libaudiofile/modules/msadpcm.c audiofile-0.2.6/libaudiofile/modules/msadpcm.c
--- audiofile-0.2.6~/libaudiofile/modules/msadpcm.c	2004-03-06 07:39:23.000000000 +0100
+++ audiofile-0.2.6/libaudiofile/modules/msadpcm.c	2009-11-28 16:44:59.863411251 +0100
@@ -129,8 +129,7 @@
 	ms_adpcm_state	*state[2];
 
 	/* Calculate the number of bytes needed for decoded data. */
-	outputLength = msadpcm->samplesPerBlock * sizeof (int16_t) *
-		msadpcm->track->f.channelCount;
+	outputLength = msadpcm->samplesPerBlock * sizeof (int16_t);
 
 	channelCount = msadpcm->track->f.channelCount;
 
@@ -180,8 +179,8 @@
 		The first two samples have already been 'decoded' in
 		the block header.
 	*/
-	samplesRemaining = (msadpcm->samplesPerBlock - 2) *
-		msadpcm->track->f.channelCount;
+	samplesRemaining = msadpcm->samplesPerBlock
+		- 2 * msadpcm->track->f.channelCount;
 
 	while (samplesRemaining > 0)
 	{
diff -urNad audiofile-0.2.6~/libaudiofile/wave.c audiofile-0.2.6/libaudiofile/wave.c
--- audiofile-0.2.6~/libaudiofile/wave.c	2009-11-28 16:44:59.722415268 +0100
+++ audiofile-0.2.6/libaudiofile/wave.c	2009-11-28 16:45:08.642428937 +0100
@@ -199,11 +199,13 @@
 		case WAVE_FORMAT_ADPCM:
 		{
 			u_int16_t	bitsPerSample, extraByteCount,
-					samplesPerBlock, numCoefficients;
+					samplesPerBlock, numCoefficients,
+					framesPerBlock;
 			int		i;
 			AUpvlist	pv;
 			long		l;
 			void		*v;
+			int		minBlockLength;
 
 			if (track->f.channelCount != 1 &&
 				track->f.channelCount != 2)
@@ -216,11 +218,33 @@
 			af_fread(&bitsPerSample, 1, 2, fp);
 			bitsPerSample = LENDIAN_TO_HOST_INT16(bitsPerSample);
 
+			if (bitsPerSample != 4)
+			{
+				_af_error(AF_BAD_WIDTH,
+					"bad sample width of %hd bits",
+					bitsPerSample);
+				return AF_FAIL;
+			}
+
 			af_fread(&extraByteCount, 1, 2, fp);
 			extraByteCount = LENDIAN_TO_HOST_INT16(extraByteCount);
 
-			af_fread(&samplesPerBlock, 1, 2, fp);
-			samplesPerBlock = LENDIAN_TO_HOST_INT16(samplesPerBlock);
+			af_fread(&framesPerBlock, 1, 2, fp);
+			framesPerBlock = LENDIAN_TO_HOST_INT16(framesPerBlock);
+
+			minBlockLength = 7 * channelCount; /* header */
+			if (framesPerBlock > 2)
+				minBlockLength += ( ( framesPerBlock - 2 ) * channelCount + 1) / 2;
+
+			if (blockAlign < minBlockLength)
+			{
+				_af_error(AF_BAD_FRAMECNT,
+					"blockAlign %hd too small for %hd samplesPerBlock",
+					blockAlign, samplesPerBlock);
+				return AF_FAIL;
+			}
+
+			samplesPerBlock = framesPerBlock *channelCount;
 
 			af_fread(&numCoefficients, 1, 2, fp);
 			numCoefficients = LENDIAN_TO_HOST_INT16(numCoefficients);
@@ -242,6 +266,7 @@
 				wave->msadpcmCoefficients[i][1] = a1;
 			}
 
+
 			track->f.sampleWidth = 16;
 			track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP;
 			track->f.compressionType = AF_COMPRESSION_MS_ADPCM;
@@ -277,18 +302,44 @@
 		{
 			AUpvlist	pv;
 			long		l;
+			int		minBlockLength;
 
 			u_int16_t	bitsPerSample, extraByteCount,
-					samplesPerBlock;
+					samplesPerBlock, framesPerBlock;
 
 			af_fread(&bitsPerSample, 1, 2, fp);
 			bitsPerSample = LENDIAN_TO_HOST_INT16(bitsPerSample);
 
+			if (bitsPerSample != 4)
+			{
+				_af_error(AF_BAD_WIDTH,
+					"bad sample width of %hd bits",
+					bitsPerSample);
+				return AF_FAIL;
+			}
+
 			af_fread(&extraByteCount, 1, 2, fp);
 			extraByteCount = LENDIAN_TO_HOST_INT16(extraByteCount);
 
-			af_fread(&samplesPerBlock, 1, 2, fp);
-			samplesPerBlock = LENDIAN_TO_HOST_INT16(samplesPerBlock);
+			af_fread(&framesPerBlock, 1, 2, fp);
+			framesPerBlock = LENDIAN_TO_HOST_INT16(framesPerBlock);
+			samplesPerBlock = framesPerBlock * channelCount;
+
+			/* per channel, ima has blocks of len 4, the 1st has 1st sample, the others
+			 * up to 8 samples per block,
+			 * so number of later blocks is (nsamp-1 + 7)/8, total blocks/chan is
+			 * (nsamp-1+7)/8 + 1 = (nsamp+14)/8
+			 */
+
+			minBlockLength = ( framesPerBlock + 14 )/8 * 4 * channelCount;
+
+			if (blockAlign < minBlockLength)
+			{
+				_af_error(AF_BAD_FRAMECNT,
+					"blockAlign %hd too small for %hd samplesPerBlock",
+					blockAlign, samplesPerBlock);
+				return AF_FAIL;
+			}
 
 			track->f.sampleWidth = 16;
 			track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP;
